Python的深拷贝和浅拷贝


python程序员貌似面试都会有这样一道题,就是问你深拷贝和浅拷贝,那就来总结一下

>>> import copy 
>>> a = [1,2,3,4,5,6,['a','b','c']]    #列表里边有列表
>>> b = a    #这是赋值的操作,id(b)=id(a)是true,说明在同一个内存的位置,b是对a列表的又一个引用,所以a、b是完全相同的,可以通过id(a)==id(b)证明
>>> c = copy.copy(a)    #对a进行了浅拷贝并传给c
>>> d = copy.deepcopy(a)    #对a进行了深拷贝并传给d
>>> a
[1, 2, 3, 4, 5, 6, ['a', 'b', 'c']]
>>> b
[1, 2, 3, 4, 5, 6, ['a', 'b', 'c']]
>>> c
[1, 2, 3, 4, 5, 6, ['a', 'b', 'c']]
>>> d
[1, 2, 3, 4, 5, 6, ['a', 'b', 'c']]
>>> a.append(5)    #对a列表末尾追加一个元素
>>> a[6].append('hello')    #对a列表内层的列表追加一个元素
>>> a
[1, 2, 3, 4, 5, 6, ['a', 'b', 'c', 'hello'], 5]    #a列表的变化很正常,是操作应该得到的结果
>>> b
[1, 2, 3, 4, 5, 6, ['a', 'b', 'c', 'hello'], 5]    #b是对a列表的又一个引用,所以a、b是完全相同的
>>> c
[1, 2, 3, 4, 5, 6, ['a', 'b', 'c', 'hello']]    #c列表的对a列表进行了浅拷贝得到的,copy.copy(浅拷贝)只拷贝父对象,不会拷贝对象的内部的子对象
>>> d
[1, 2, 3, 4, 5, 6, ['a', 'b', 'c']]    #d列表是a列表进行了深拷贝,copy.deepcopy(深拷贝)拷贝对象及其子对象
id(a) = id(b) != id(c) != id(d)

浅拷贝是指拷贝的只是原对象元素的引用,换句话说,浅拷贝产生的对象本身是新的,但是它的内容不是新的,只是对原对象的一个引用

>>> List1=[[1, 2], 3, 4]
>>> List2 = aList[:]    #利用切片完成一次浅拷贝
>>> id(List1)
3084416588L
>>> id(List2)
3084418156L
>>> List1[0][0] = 5
>>> List1
[[5, 2], 3, 4]
>>> List2
[[5, 2], 3, 4]

可以看到,浅拷贝生产了一个新的对象List2,但是List1的内容确实对List1的引用,所以但改变List1中值的时候,List2的值也跟着变化了。

但是有点需要特别提醒的,如果对象本身是不可变的,那么浅拷贝时也会产生两个值,见这个例子:

>>> List1 = [1, 2]
>>> List2 = List1[:]
>>> List2
[1, 2]
>>> List1
[1, 2]
>>> List1[1]=111
>>> List1
[1, 111]
>>> List2
[1, 2]

为什么List2的第二个元素没有变成111呢?因为数字在python中是不可变类型!!

这个顺便回顾下Python标准类型的分类:
可变类型: 列表,字典
不可变类型:数字,字符串,元组

对象赋值实际上是简单的对象引用

>>> a = 1
>>> id(a)
135720760
>>> b = a
>>> id(b)
135720760

a和b完全是一回事。


热评文章